#include "ota_version.h"
#include <openssl/sha.h>
#include "sys/reboot.h"
#include "time.h"

#define OTA_VERION_URL "http://192.168.56.88:8000/ota_server/ota_version_info.json"
#define OTA_FILE_URL "http://192.168.56.88:8000/ota_server/gateway"
#define OTA_FILE_PATH "/usr/bin/gateway.update"

#define LOCAL_VERSION "{\"major\": 1, \"minor\": 0, \"patch\": 1}"

typedef struct
{
    int major;
    int minor;
    int patch;
    char *hash1;
} version_info_t;

char *get_file_sha1(const char *filepath)
{
    FILE *fp = fopen(filepath, "rb");
    if (!fp)
    {
        perror("fopen");
        return NULL;
    }

    // 创建 SHA1 上下文
    SHA_CTX ctx;
    SHA1_Init(&ctx);

    unsigned char buffer[4096];
    size_t bytes_read;

    // 读取文件并更新 SHA1
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp)) != 0)
    {
        SHA1_Update(&ctx, buffer, bytes_read);
    }

    fclose(fp);

    // 获取输出（20字节）
    unsigned char digest[SHA_DIGEST_LENGTH]; // SHA_DIGEST_LENGTH == 20
    SHA1_Final(digest, &ctx);

    // 转成十六进制字符串（40字节 + '\0'）
    char *hex = malloc(SHA_DIGEST_LENGTH * 2 + 1);
    if (!hex)
    {
        return NULL;
    }

    for (int i = 0; i < SHA_DIGEST_LENGTH; i++)
    {
        sprintf(hex + i * 2, "%02x", digest[i]);
    }
    hex[40] = '\0';

    return hex;
}

void ota_version_parse_version_info(char *json, version_info_t *version_info)
{
    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        log_error("parse json error");
        return;
    }
    version_info->major = cJSON_GetObjectItem(root, "major")->valueint;
    version_info->minor = cJSON_GetObjectItem(root, "minor")->valueint;
    version_info->patch = cJSON_GetObjectItem(root, "patch")->valueint;

    cJSON *hash1Item = cJSON_GetObjectItem(root, "hash1");
    if (hash1Item)
    {
        version_info->hash1 = strdup(hash1Item->valuestring);
    }

    cJSON_Delete(root);
}

void ota_version_check(void)
{
    version_info_t local_version;
    version_info_t remote_version;

    char *version_info = ota_http_get_text(OTA_VERION_URL);

    // log_info("version info: %s", version_info);
    ota_version_parse_version_info(LOCAL_VERSION, &local_version);
    ota_version_parse_version_info(version_info, &remote_version);

    // 打印版本信息
    log_info("local version: %d.%d.%d", local_version.major, local_version.minor, local_version.patch);
    log_info("remote version: %d.%d.%d %s", remote_version.major, remote_version.minor, remote_version.patch, remote_version.hash1);

    if (remote_version.major < local_version.major ||
        (remote_version.major == local_version.major && remote_version.minor < local_version.minor) ||
        (remote_version.major == local_version.major && remote_version.minor == local_version.minor && remote_version.patch <= local_version.patch))

    {
        log_info("不需要升级...");
        return;
    }
    log_info("需要升级...");

    gate_state_t state = ota_http_download(OTA_FILE_URL, OTA_FILE_PATH);
    if (state != GATE_OK)
    {
        log_error("下载失败...");
        return;
    }
    log_info("下载成功...");
    log_info("开始做hash校验...");

    char *file_sha1 = get_file_sha1(OTA_FILE_PATH);

    if (strcmp(file_sha1, remote_version.hash1) != 0)
    {
        log_error("hash校验失败...");
        return;
    }
    log_info("hash校验成功...");

    // 会写一个脚本, 对下载 的文件进行改名. 脚本在开机会自动启动
    // reboot(RB_AUTOBOOT);
}

void ota_version_auto_update(void)
{
    ota_version_check();
    while (1)
    {
        // 当前时间的时间戳: 是一个数字, 表示一个s, 从1970-01-01 00:00:00开始
        time_t now = time(NULL);

        struct tm *t = localtime(&now);
        if (t->tm_hour == 11 && t->tm_min == 23)
        {
            ota_version_check();
        }
        log_info("等待下一次检查...");
        sleep(60); //每分钟检测1次
    }
}
